package deng.java.examples;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Properties;
import java.util.Set;

/**
 * 
 * A command line program that execute any non-argument method defined in this class. Default method
 * is help(), or use first command argument as method name.
 * 
 * @author zemian
 *
 */
public class Main extends MainHelper implements Runnable {
	
	public static void main(String[] args) { 
		new Main(args).run(); 
	}
	
	private String[] args;
	
	public Main(String[] args) {
		this.args = args; 
	}

	@Override
	public void run() {
		if (args.length < 1) { help(); }
		else {
			String name = args[0];
			Class<?>[] paramTypes = new Class[0];
			try {
				Method meth = Main.class.getMethod(name, paramTypes);
				Object[] params = new Object[0];
				Object ret = meth.invoke(this, params);
				if (ret != null) { println(ret); }
			} catch (Exception e) {
				throw new RuntimeException(e);
			} 
		}
	}
	
	/**
	 * Print a list of all available methods.
	 */
	public void help() {
		println("java Main <methodName>");
		println(">> methodNames:");

		// Print all methods available except those excludes list.
		Set<String> excludes = new HashSet<String>();
		for (String name : "run wait hashCode getClass toString notify notifyAll".split(" ")) {
			excludes.add(name);
		}
		Method[] methAry = Main.class.getMethods();
		for (Method meth : methAry) {
			if (meth.getParameterTypes().length == 0 && !excludes.contains(meth.getName())) {
				println("  " + meth.getName());
			}
		}		
	}
	
	/**
	 * Print System Properties in sorted order.
	 */
	public void sysprops() {
		Properties props = System.getProperties();
		List<String> names = new ArrayList<String>(props.stringPropertyNames());
		Collections.sort(names);
		for (String name : names) { println(name + " : " + props.getProperty(name)); }
	}
	
}
